#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include "../logs/log.h"

void bench(const std::string &loggerName, size_t threadCount, size_t msgCount, size_t msgLen)
{
    // 1.获取日志器
    Log::Logger::ptr logger = Log::getLogger(loggerName);
    if (logger.get() == nullptr)
    {
        // 没有对应的日志器
        return;
    }
    std::cout << "测试日志: " << msgCount << " 条, 总大小: " << (msgCount * msgLen) / 1024 << "KB\n";
    // 2.组织指定长度的日志消息
    std::string msg(msgLen-1, 'B'); //少一个字节, 是为了给末尾加换行
    msg.push_back('\n');

    // 3.创建指定数量的线程
    std::vector<double> costArray;  //用来存放线程写日志耗费时间的数组
    size_t msgAverThread = msgCount / threadCount; // 每个线程需要写的日志条数
    std::vector<std::thread> threads;
    for (int i = 0; i < threadCount; ++i)
    {
        threads.emplace_back([&, i]()
            {
                // 4.线程函数内部开始计时
                std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
                // 5.开始循环写日志
                for (int j = 0; j < msgAverThread; ++j)
                {
                    logger->FATAL("%s", msg.c_str());
                }
                // 6.线程函数内部结束计时
                std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
                std::chrono::duration<double> cost = end - start;
                costArray.push_back(cost.count());
                std::cout << "线程" << i << ": " << "\t输出数量: " << msgAverThread << ", 耗时: " << cost.count() << "s" << std::endl;
            });
    }
    
    for (int i = 0; i < threadCount; ++i)
    {
        threads[i].join();
    }
    // 7.计算相关数据 --- 在多线程中, 每个线程都会耗费时间, 但是线程是并发处理的, 因此耗时最高的那个就是总时间
    double maxCost = costArray[0];
    for(const auto& cost : costArray)
    {
        maxCost = maxCost < cost ? cost : maxCost;
    }
    size_t outputPerSecond = msgCount / maxCost; //每秒输出的日志条数
    size_t sizeOutPerSecond = (msgCount * msgLen) / (maxCost*1024); //每秒输出的日志数据大小
    //8.进行日志打印
    std::cout << "每秒输出日志数量: " << outputPerSecond << "条\n";
    std::cout << "每秒输出日志大小: " << sizeOutPerSecond << "KB\n";
}

void syncBench()
{
    std::unique_ptr<Log::LoggerBuilder> builder(new Log::GlobalLoggerBuilder());
    builder->buildLoggerType(Log::LoggerType::LOGGER_SYNC); // 日志器类型的选择: 同步日志器/异步日志器
    const std::string loggerName = "syncLogger";
    // builder->buildEnableDynamicAsync(Log::BufferType::DYNAMICGROW);   //日志器的缓冲区类型: 动态增长类型的缓冲区
    builder->buildLoggerName(loggerName);
    builder->buildFormatter("%m%n");
    builder->buildSinks<Log::FileLogSink>("./logfile/sync.log");
    Log::Logger::ptr logger = builder->build();
    bench(loggerName, 1, 1000000, 100);
}
void asyncBench()
{
    std::unique_ptr<Log::LoggerBuilder> builder(new Log::GlobalLoggerBuilder());
    builder->buildLoggerType(Log::LoggerType::LOGGER_ASYNC); // 日志器类型的选择: 同步日志器/异步日志器
    const std::string loggerName = "asyncLogger";
    //日志器的缓冲区类型: 动态增长类型的缓冲区 --- 是为了将实际的落地时间排除在外, 因为如果缓冲区中写满了, 需要等待日志的实际落地
    builder->buildEnableDynamicAsync(Log::BufferType::DYNAMICGROW);   
    builder->buildLoggerName(loggerName);
    builder->buildFormatter("%m%n");
    builder->buildSinks<Log::FileLogSink>("./logfile/async.log");
    Log::Logger::ptr logger = builder->build();
    bench(loggerName, 5, 2000000, 100);
   
}

int main()
{
    asyncBench();
    return 0;
}


